﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using psafth.AMB;
using iTextSharp.text;
using iTextSharp.text.pdf;
using System.IO;
using System.Drawing;
using System.Windows;
using psafth.RCTiming.Common;
using System.Text.RegularExpressions;

namespace psafth.RCTiming.Main.Reporting
{
    class PDFHelper
    {
        private static iTextSharp.text.Font _calibri = FontFactory.GetFont("Calibri", 9, iTextSharp.text.Font.NORMAL);
        private static iTextSharp.text.Font _calibriBold = FontFactory.GetFont("Calibri", 10, iTextSharp.text.Font.BOLD);
        private static iTextSharp.text.Font _calibriHeader = FontFactory.GetFont("Calibri", 60, iTextSharp.text.Font.BOLD);
        private static iTextSharp.text.Font _calibriStrikeThrough = FontFactory.GetFont("Calibri", 10, iTextSharp.text.Font.STRIKETHRU);

        public static void CreateStartList(Event evnt)
        {
            if (evnt.Heats == null || evnt.Heats.Count < 1)
                return;

            string filePath = string.Format("{0} {1}.pdf", Regex.Replace(evnt.EventName, @"[^0-9a-zA-Z]+", " "), DateTime.Now.ToString("yyyy-MM-dd HH mm"));

            //Create Document class object and set its size to letter and give space left, right, Top, Bottom Margin
            Document doc = new Document(iTextSharp.text.PageSize.A4, 30, 20, 2, 35);

            PdfWriter wri = PdfWriter.GetInstance(doc, new FileStream(filePath, FileMode.Create));
            //Open Document to write
            doc.Open();

            iTextSharp.text.Font cbh = new iTextSharp.text.Font(_calibriHeader);

            cbh.Size = 30;
            cbh.SetStyle(1);

            Chunk h = new Chunk(evnt.EventName, cbh);

            System.Drawing.Bitmap bitmap = null;
            string base64Logo = Properties.Settings.Default.UserLogo;

            if (!string.IsNullOrWhiteSpace(base64Logo))
            {
                byte[] bytes = Convert.FromBase64String(base64Logo);
                System.IO.MemoryStream mem = new System.IO.MemoryStream(bytes);
                bitmap = new Bitmap(mem);
            }
            else
            {
                bitmap = new Bitmap(Application.GetResourceStream(new Uri("/GFX/icon32x32.ico", UriKind.RelativeOrAbsolute)).Stream);
            }

            ImageConverter ic = new ImageConverter();

            iTextSharp.text.Image logo = iTextSharp.text.Image.GetInstance((byte[])ic.ConvertTo(bitmap, typeof(byte[])));

            logo.ScaleAbsolute(100f, 100f);
            logo.SetAbsolutePosition(480, 720);
            logo.Alignment = iTextSharp.text.Image.TEXTWRAP;

            doc.Add(logo);

            Paragraph paragraph = new Paragraph(h);

            doc.Add(paragraph);


            foreach (var heatGroups in evnt.Heats.GroupBy(d => d.Group))
            {
                foreach (Heat heat in heatGroups)
                {
                    PdfPTable heatTable = new PdfPTable(4);

                    heatTable.TotalWidth = 400f;
                    heatTable.LockedWidth = true;
                    heatTable.SetWidths(new float[] { 1f, 5f, 2f, 1f });

                    heatTable.HorizontalAlignment = 0;

                    //leave a gap before and after the table

                    heatTable.SpacingBefore = 2f;

                    heatTable.SpacingAfter = 15f;

                    heatTable.DefaultCell.Padding = 3;
                    heatTable.DefaultCell.BorderColor = BaseColor.WHITE;

                    Chunk f = new Chunk("NR", new iTextSharp.text.Font(_calibriBold));
                    Chunk y = new Chunk("Namn", new iTextSharp.text.Font(_calibriBold));
                    Chunk u = new Chunk("Transponder", new iTextSharp.text.Font(_calibriBold));
                    Chunk w = new Chunk("Licens", new iTextSharp.text.Font(_calibriBold));

                    heatTable.AddCell(new Phrase(f));
                    heatTable.AddCell(new Phrase(y));
                    heatTable.AddCell(new Phrase(u));
                    heatTable.AddCell(new Phrase(w));

                    foreach (HeatCompetitor hc in heat.HeatCompetitors)
                    {
                        Chunk sn = new Chunk(hc.StartNumber.ToString(), new iTextSharp.text.Font(_calibri));
                        Chunk fn = new Chunk(hc.FullName, new iTextSharp.text.Font(_calibri));
                        Chunk tn = new Chunk(hc.TransponderId.ToString(), new iTextSharp.text.Font(_calibri));
                        Chunk li = new Chunk(hc.LicenceNumber, new iTextSharp.text.Font(_calibri));

                        heatTable.AddCell(new Phrase(sn));
                        heatTable.AddCell(new Phrase(fn));
                        heatTable.AddCell(new Phrase(tn));
                        heatTable.AddCell(new Phrase(li));
                    }

                    Chunk title = new Chunk(string.Format("{0} - Group {1}", heat.RaceClass.Name, heat.Group), new iTextSharp.text.Font(_calibriBold));

                    Paragraph titleParagraph = new Paragraph();
                    titleParagraph.Add(title);

                    doc.Add(titleParagraph);
                    doc.Add(heatTable);
                }
            }

            doc.Close(); //Close document

            System.Diagnostics.Process.Start(filePath);

        }

        public static void CreateHeatResult(ObservableCollectionExt<HeatCompetitor> competitors, string header)
        {
            if (competitors.Count < 1)
                return;

            string filePath = string.Format("{0} {1}.pdf", Regex.Replace(header, @"[^0-9a-zA-Z]+", " "), DateTime.Now.ToString("yyyy-MM-dd HH mm"));

            List<HeatCompetitor> sortedCompetitors = new List<HeatCompetitor>(competitors);

            sortedCompetitors.Sort(StartnumberComparison);

            if (sortedCompetitors.Sum(l => l.Laps.Count()) > 0)
            {
                sortedCompetitors.Sort((first, second) =>
                {
                    int result = first.Laps.Count(la => la.IsValid).CompareTo(second.Laps.Count(la => la.IsValid));
                    return result != 0 ? result : second.FinishTime.CompareTo(first.FinishTime);
                });
            }

            //Create Document class object and set its size to letter and give space left, right, Top, Bottom Margin
            Document doc = new Document(iTextSharp.text.PageSize.A4.Rotate(), 20, 20, 2, 35);

            filePath = filePath.Replace(':', '-');
            filePath = filePath.Replace('/', '-');

            PdfWriter wri = PdfWriter.GetInstance(doc, new FileStream(filePath, FileMode.Create));
            doc.Open();//Open Document to write

            iTextSharp.text.Font cbh = new iTextSharp.text.Font(_calibriHeader);

            cbh.Size = 30;
            cbh.SetStyle(1);

            Chunk h = new Chunk(header, cbh);

            System.Drawing.Bitmap bitmap = null;
            string base64Logo = Properties.Settings.Default.UserLogo;

            if (!string.IsNullOrWhiteSpace(base64Logo))
            {
                byte[] bytes = Convert.FromBase64String(base64Logo);
                System.IO.MemoryStream mem = new System.IO.MemoryStream(bytes);
                bitmap = new Bitmap(mem);
            }
            else
            {
                bitmap = new Bitmap(Application.GetResourceStream(new Uri("/GFX/icon32x32.ico", UriKind.RelativeOrAbsolute)).Stream);
            }

            ImageConverter ic = new ImageConverter();

            iTextSharp.text.Image logo = iTextSharp.text.Image.GetInstance((byte[])ic.ConvertTo(bitmap, typeof(byte[])));

            logo.ScaleAbsolute(100f, 100f);
            logo.SetAbsolutePosition(720, 480);
            logo.Alignment = iTextSharp.text.Image.TEXTWRAP;

            doc.Add(logo);

            Paragraph paragraph = new Paragraph(h);

            PdfPTable ResultTable = new PdfPTable(4);

            ResultTable.TotalWidth = 400f;
            ResultTable.LockedWidth = true;
            ResultTable.SetWidths(new float[] { 4f, 2f, 1f, 2f });

            ResultTable.HorizontalAlignment = 0;

            //leave a gap before and after the table

            ResultTable.SpacingBefore = 15f;

            ResultTable.SpacingAfter = 15f;

            ResultTable.DefaultCell.Padding = 3;
            ResultTable.DefaultCell.BorderColor = BaseColor.GRAY;

            Chunk f = new Chunk("Namn", new iTextSharp.text.Font(_calibriBold));
            Chunk y = new Chunk("Varv", new iTextSharp.text.Font(_calibriBold));
            Chunk u = new Chunk("B. varv", new iTextSharp.text.Font(_calibriBold));
            Chunk w = new Chunk("Transponder", new iTextSharp.text.Font(_calibriBold));

            ResultTable.AddCell(new Phrase(f));
            ResultTable.AddCell(new Phrase(y));
            ResultTable.AddCell(new Phrase(u));
            ResultTable.AddCell(new Phrase(w));

            PdfPTable TimeTable = new PdfPTable(competitors.Count);
            //actual width of table in points

            TimeTable.TotalWidth = competitors.Count * 66f;

            //fix the absolute width of the table

            TimeTable.LockedWidth = true;

            //relative col widths in proportions - 1/3 and 2/3

            float[] widths = new float[competitors.Count];

            for (int i = 0; i < widths.Length; i++)
            {
                widths[i] = 1f;
            }

            TimeTable.SetWidths(widths);

            TimeTable.HorizontalAlignment = 0;

            //leave a gap before and after the table

            TimeTable.SpacingBefore = 15f;

            TimeTable.SpacingAfter = 15f;

            sortedCompetitors.Reverse();

            double bestofall = 30 * 1000;

            foreach (HeatCompetitor boa in sortedCompetitors)
            {
                if (boa.BestLapTime > 0)
                {
                    if (boa.BestLapTime <= bestofall)
                        bestofall = boa.BestLapTime;
                }
            }

            int Position = 1;
            foreach (HeatCompetitor c in sortedCompetitors)
            {
                iTextSharp.text.Font b = new iTextSharp.text.Font(_calibri);
                if (c.BestLapTime == bestofall)
                    b = new iTextSharp.text.Font(_calibriBold);

                b.Size = 12;

                Chunk n;

                if (c.StartNumber > 0)
                {
                    n = new Chunk(Position + ". [" + c.StartNumber + "] " + c.FullName, b);
                }
                else
                {
                    if (c != null && !string.IsNullOrWhiteSpace(c.FullName))
                    {
                        n = new Chunk(Position + ". " + c.FullName, b);
                    }
                    else
                    {
                        n = new Chunk(Position + ". Okänd", b);
                    }
                }

                Phrase pName = new Phrase(n);

                Chunk l;

                if (c.FinishTime < 0)
                {
                    l = new Chunk(string.Format("{0} (DSQ)", c.Laps.Count(la => la.IsValid).ToString()), b);
                }
                else
                {
                    l = new Chunk(string.Format("{0} ({1}s)", c.Laps.Count(la => la.IsValid).ToString(), AMBCalculator.TrimDouble(c.FinishTime, 3)), b);
                }

                Phrase pLaps = new Phrase(l);

                Chunk t = new Chunk(c.TransponderId.ToString(), b);

                Phrase pTransp = new Phrase(t);

                string BestLap = string.Empty;

                BestLap = c.BestLapTime.ToString("0.000");

                if (c.BestLapTime == -1.0)
                    BestLap = "-";

                if (c.BestLapTime == -2.0)
                    BestLap = "ERROR";

                Chunk be = new Chunk(BestLap, b);
                Phrase pBest = new Phrase(be);

                ResultTable.AddCell(pName);
                ResultTable.AddCell(pLaps);
                ResultTable.AddCell(pBest);
                ResultTable.AddCell(pTransp);

                Position++;
            }


            foreach (HeatCompetitor t in competitors)
            {
                Phrase ps = new Phrase();

                iTextSharp.text.Font b = new iTextSharp.text.Font(_calibri);
                b.SetStyle(1);
                b.Size = 7;

                Chunk g;

                if (t != null && t.FullName != null)
                {
                    g = new Chunk(t.LicenceNumber + Environment.NewLine + t.FullName.Substring(0, 1) + ". " + t.LastName + Environment.NewLine, b);
                }
                else
                {
                    g = new Chunk("-" + Environment.NewLine + "Okänd" + Environment.NewLine, b);
                }
                ps.Add(g);

                int c = 0;

                double best = t.BestLapTime;

                foreach (Lap l in t.Laps)
                {
                    string isManual = string.Empty;

                    if (l.ManualCount)
                        isManual = "*";

                    c++;
                    if (l.LapTime == best)
                    {
                        iTextSharp.text.Font bt = new iTextSharp.text.Font(_calibriBold);
                        bt.SetStyle(1);
                        bt.Size = 9;

                        ps.Add(new Chunk(c.ToString("00") + " | " + l.LapTime.ToString("0.000") + isManual + Environment.NewLine, bt));

                    }
                    else
                    {
                        iTextSharp.text.Font bt;
                        if (l.IsValid)
                        {
                            bt = new iTextSharp.text.Font(_calibri);
                            bt.SetStyle(0);
                            bt.Size = 9;
                            ps.Add(new Chunk(c.ToString("00") + " | " + l.LapTime.ToString("0.000") + isManual + Environment.NewLine, bt));
                        }
                        else
                        {
                            string type = string.Empty;

                            if (l.InvalidReason == Lap.InvalidationType.CORRECTION)
                                type = "C";

                            if (l.InvalidReason == Lap.InvalidationType.PENALTY)
                                type = "P";

                            bt = new iTextSharp.text.Font(_calibriStrikeThrough);
                            bt.SetStyle(iTextSharp.text.Font.STRIKETHRU);
                            bt.Size = 9;
                            ps.Add(new Chunk(c.ToString("00") + " | " + l.LapTime.ToString("0.000") + isManual, bt));

                            iTextSharp.text.Font tmpFnt = new iTextSharp.text.Font(_calibri);
                            tmpFnt.SetStyle(0);
                            tmpFnt.Size = 9;

                            ps.Add(new Chunk(" " + type + Environment.NewLine, tmpFnt));

                            c--;
                        }
                    }
                }

                PdfPCell pc = new PdfPCell(ps);

                pc.Border = 0;

                TimeTable.AddCell(pc);
            }

            doc.Add(paragraph);

            doc.Add(ResultTable);

            doc.Add(TimeTable);

            doc.Close(); //Close document

            System.Diagnostics.Process.Start(filePath);
        }

        public static Comparison<HeatCompetitor> StartnumberComparison = delegate(HeatCompetitor p1, HeatCompetitor p2)
{
    if (!p1.StartNumber.HasValue)
        p1.StartNumber = 0;

    if (!p2.StartNumber.HasValue)
        p2.StartNumber = 0;

    return p2.StartNumber.Value.CompareTo(p1.StartNumber.Value);
};

        static double NextDouble(Random rng, double min, double max)
        {
            return min + (rng.NextDouble() * (max - min));
        }
    }
}
